package com.swak.frame.api.filter.interceptor;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.AnnotationUtils;

import com.swak.frame.filter.ApiAuthCodeUtil;
import com.swak.frame.filter.SwakMethodAnnotationParser;
import com.swak.frame.filter.annotation.ApiFilterOperation;
import com.swak.frame.filter.annotation.SwakMethod;
import com.swak.frame.filter.annotation.SwakService;
import com.swak.frame.interceptor.SwakAnnotationUtils;

public class ApiFilterAnnotationParser implements SwakMethodAnnotationParser {
	
	private static final Set<Class<? extends Annotation>> SWAK_METHOD_ANNOTATIONS = new LinkedHashSet<>(1);
	static {
		SWAK_METHOD_ANNOTATIONS.add(SwakMethod.class);
	}


	/**
	 * {@link SwakMethod} not support class,@Target is method
	 */
	@Override
	public Collection<ApiFilterOperation> parseAnnotations(Class<?> type) {
		return Collections.emptyList();
	}

	@Override
	public Collection<ApiFilterOperation> parseAnnotations(Method method,Class<?> targetClass) {
		Collection<? extends Annotation> anns = SwakAnnotationUtils.parseAnnotations(method, SWAK_METHOD_ANNOTATIONS);
		if (CollectionUtils.isNotEmpty(anns)) {
			// 处理 RateLimit和SwakMethod
			final Collection<ApiFilterOperation> operation = new ArrayList<>(1);
			anns.stream().filter(ann -> (ann instanceof SwakMethod))
					.forEach(ann -> operation.add(parseApiFilterAnnotation(method, targetClass, ann)));
			return operation;
		}
		return Collections.emptyList();
	}

	private ApiFilterOperation parseApiFilterAnnotation(Method method, Class<?> targetClass, Annotation ann) {
		SwakMethod swakMethod = (SwakMethod) ann;
		SwakService swakService = AnnotationUtils.getAnnotation(targetClass,SwakService.class);
		String resource = ApiAuthCodeUtil.getAuthCode(swakService, swakMethod, method);		
		return ApiFilterOperation.newOperation(resource, swakMethod);
	}

	@Override
	public boolean isCandidateClass(Class<?> targetClass) {
		return AnnotatedElementUtils.hasAnnotation(targetClass, SwakService.class);
	}
}
